package com.zhentao.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhentao.pojo.Menu;
import com.zhentao.service.impl.MenuServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 菜单管理控制器
 * @author 杨旭朋
 * @date 2025/1/1
 */
@RequestMapping("/manpower/menu")
@RestController
public class MenuController {

    @Autowired
    private MenuServiceImpl menuService;

    /**
     * 分页查询菜单列表
     */
    @PostMapping("list")
    public Page<Menu> getMenuList(@RequestBody MenuQueryVO queryVO) {
        Page<Menu> page = new Page<>(queryVO.getPageNum(), queryVO.getPageSize());

        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        if (queryVO.getName() != null && !queryVO.getName().trim().isEmpty()) {
            queryWrapper.like("name", queryVO.getName());
        }
        if (queryVO.getPath() != null && !queryVO.getPath().trim().isEmpty()) {
            queryWrapper.like("path", queryVO.getPath());
        }
        if (queryVO.getType() != null) {
            queryWrapper.eq("type", queryVO.getType());
        }
        queryWrapper.orderByAsc("sort");

        return menuService.page(page, queryWrapper);
    }

    /**
     * 添加菜单
     */
    @PostMapping("add")
    public String addMenu(@RequestBody Menu menu) {
        // 检查菜单名称是否已存在（同级菜单下）
        Menu existMenu = menuService.getOne(Wrappers.<Menu>lambdaQuery()
                .eq(Menu::getName, menu.getName())
                .eq(Menu::getParentId, menu.getParentId()));
        if (existMenu != null) {
            return "同级菜单下已存在相同名称的菜单";
        }

        // 检查菜单路径是否已存在
        if (menu.getPath() != null && !menu.getPath().trim().isEmpty()) {
            existMenu = menuService.getOne(Wrappers.<Menu>lambdaQuery()
                    .eq(Menu::getPath, menu.getPath()));
            if (existMenu != null) {
                return "菜单路径已存在";
            }
        }

        menu.setCreateTime(new Date());
        menu.setUpdateTime(new Date());

        boolean result = menuService.save(menu);
        return result ? "添加成功" : "添加失败";
    }

    /**
     * 更新菜单
     */
    @PostMapping("update")
    public String updateMenu(@RequestBody Menu menu) {
        // 检查菜单名称是否已存在（同级菜单下，排除当前菜单）
        Menu existMenu = menuService.getOne(Wrappers.<Menu>lambdaQuery()
                .eq(Menu::getName, menu.getName())
                .eq(Menu::getParentId, menu.getParentId())
                .ne(Menu::getId, menu.getId()));
        if (existMenu != null) {
            return "同级菜单下已存在相同名称的菜单";
        }

        // 检查菜单路径是否已存在（排除当前菜单）
        if (menu.getPath() != null && !menu.getPath().trim().isEmpty()) {
            existMenu = menuService.getOne(Wrappers.<Menu>lambdaQuery()
                    .eq(Menu::getPath, menu.getPath())
                    .ne(Menu::getId, menu.getId()));
            if (existMenu != null) {
                return "菜单路径已存在";
            }
        }

        // 检查是否将菜单设置为自己的子菜单
        if (menu.getParentId() != null && menu.getParentId().equals(menu.getId())) {
            return "不能将菜单设置为自己的子菜单";
        }

        // 检查是否将菜单设置为自己的后代菜单
        if (menu.getParentId() != null && isDescendant(menu.getId(), menu.getParentId())) {
            return "不能将菜单设置为自己的后代菜单";
        }

        menu.setUpdateTime(new Date());
        boolean result = menuService.updateById(menu);
        return result ? "更新成功" : "更新失败";
    }

    /**
     * 删除菜单
     */
    @PostMapping("delete")
    public String deleteMenu(@RequestParam("id") Long id) {
        // 检查是否有子菜单
        long childCount = menuService.count(Wrappers.<Menu>lambdaQuery()
                .eq(Menu::getParentId, id));
        if (childCount > 0) {
            return "该菜单下有子菜单，不能删除";
        }

        // 检查是否有角色关联此菜单
        // TODO: 这里需要检查角色菜单关联表

        boolean result = menuService.removeById(id);
        return result ? "删除成功" : "删除失败";
    }

    /**
     * 根据ID获取菜单信息
     */
    @PostMapping("getById")
    public Menu getMenuById(@RequestParam("id") Long id) {
        return menuService.getById(id);
    }

    /**
     * 获取菜单树
     */
    @PostMapping("getMenuTree")
    public List<Menu> getMenuTree() {
        List<Menu> allMenus = menuService.list(Wrappers.<Menu>lambdaQuery()
                .orderByAsc(Menu::getSort));

        return buildMenuTree(allMenus);
    }

    /**
     * 获取所有菜单（用于下拉选择）
     */
    @PostMapping("getAll")
    public List<Menu> getAllMenus() {
        return menuService.list(Wrappers.<Menu>lambdaQuery()
                .orderByAsc(Menu::getSort));
    }

    /**
     * 构建菜单树
     */
    private List<Menu> buildMenuTree(List<Menu> menus) {
        Map<Long, List<Menu>> parentMap = menus.stream()
                .collect(Collectors.groupingBy(Menu::getParentId));

        return buildTreeRecursive(0L, parentMap);
    }

    /**
     * 递归构建树结构
     */
    private List<Menu> buildTreeRecursive(Long parentId, Map<Long, List<Menu>> parentMap) {
        List<Menu> children = parentMap.get(parentId);
        if (children == null) {
            return new ArrayList<>();
        }

        for (Menu menu : children) {
            List<Menu> childMenus = buildTreeRecursive(menu.getId(), parentMap);
            menu.setChildren(childMenus);
        }

        return children;
    }

    /**
     * 检查是否为后代菜单
     */
    private boolean isDescendant(Long menuId, Long parentId) {
        if (parentId == null || parentId == 0) {
            return false;
        }

        Menu parent = menuService.getById(parentId);
        if (parent == null) {
            return false;
        }

        if (parent.getParentId() != null && parent.getParentId().equals(menuId)) {
            return true;
        }

        return isDescendant(menuId, parent.getParentId());
    }

    /**
     * 菜单查询VO
     */
    public static class MenuQueryVO {
        private Integer pageNum = 1;
        private Integer pageSize = 10;
        private String name;
        private String path;
        private Integer type;

        // getters and setters
        public Integer getPageNum() { return pageNum; }
        public void setPageNum(Integer pageNum) { this.pageNum = pageNum; }
        public Integer getPageSize() { return pageSize; }
        public void setPageSize(Integer pageSize) { this.pageSize = pageSize; }
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getPath() { return path; }
        public void setPath(String path) { this.path = path; }
        public Integer getType() { return type; }
        public void setType(Integer type) { this.type = type; }
    }
}
